package com.example.server;

import com.example.message.TextMessage;
import com.example.service.HazelcastService;
import com.example.utils.SpringUtils;
import com.hazelcast.collection.IList;
import com.hazelcast.collection.ItemEvent;
import com.hazelcast.collection.ItemListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Service;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;


@ServerEndpoint("/websocket/{uid}")
@Service
public class WebSocketServerImpl implements WebSocketServer, ItemListener, CommandLineRunner {

    Logger logger = LoggerFactory.getLogger(WebSocketServerImpl.class);

    private static Map<String, Session> maps = new ConcurrentHashMap<>();

    public static final String LIST = "LIST";

    @OnOpen
    public void onOpen(Session session, @PathParam("uid") String uid) {
        maps.put(uid, session);
    }

    @OnClose
    public void onClose(@PathParam("uid") String uid) {
        maps.remove(uid);
    }

    @OnMessage
    public void onMessage(Session session, String message, @PathParam("uid") String uid) {
        HazelcastService hazelcastService = (HazelcastService) SpringUtils.getBean(HazelcastService.class);
        IList list = hazelcastService.getHazelcastInstance().getList(LIST);
        TextMessage textMessage = new TextMessage();
        textMessage.setToId(uid);
        textMessage.setContext(message);
        list.add(textMessage);
    }

    @Override
    public int getOnLineSize() {
        return maps.keySet().size();
    }

    @Override
    public Set getOnLine() {
        return maps.keySet();
    }

    @Override
    public Session getSession(String userId) {
        return maps.get(userId);
    }

    @Override
    public void run(String... args) throws Exception {
        HazelcastService hazelcastService = (HazelcastService) SpringUtils.getBean(HazelcastService.class);
        IList list = hazelcastService.getHazelcastInstance().getList(LIST);
        list.addItemListener(this, true);
    }

    @Override
    public void itemAdded(ItemEvent item) {
        TextMessage textMessage = (TextMessage) item.getItem();
        for (String userId : maps.keySet()) {
            if (!userId.equalsIgnoreCase(textMessage.getToId())) {
                Session session = maps.get(userId);
                try {
                    session.getBasicRemote().sendText(textMessage.getContext());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void itemRemoved(ItemEvent item) {

    }
}